home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 8 / FM Towns Free Software Collection 8.iso / t_os / wink24h / src / bplus.c next >
Text File  |  1994-06-01  |  40KB  |  1,629 lines

  1. /**************************************************************************
  2.  
  3.     FMR version Makeing by ken 89.9.5
  4.  
  5. ***************************************************************************/
  6. #include    <stdio.h>
  7. #include    <time.h>
  8. #include    <string.h>
  9. #include    <fmcfrb.h>
  10. #include    "defs.h"
  11.  
  12. #define    TRUE    1
  13. #define    FALSE    0
  14. #define    ERR    (-1)
  15.  
  16. #define    UNSIG    unsigned short
  17. #define unlink    remove
  18.  
  19. #define    Async_Send(c)    send_aux(c)
  20. #define    Bufferd_Recive    recv_aux
  21. #define    Bufferd_Send(c)    send_aux(c)
  22.  
  23. void    Bufferd_Flush()
  24. {
  25. }
  26.  
  27. #define    WRITE_OP     "wb"
  28. #define    READ_OP         "rb"
  29. #define    UPDATE_OP    "r+b"
  30.  
  31. extern    unsigned char *cvram;
  32.  
  33. extern    void    Send_Failure();
  34. extern    int    kbhit();
  35. extern    int    getch();
  36. extern    void    wrtstr();
  37. extern    void    Dmy_form();
  38. extern    void    Dsp_vram();
  39. extern    int    recv_aux();
  40. extern    void    send_aux();
  41.  
  42. #define STMsg        0
  43. #define STFile       1
  44. #define STUpDow      2
  45. #define STType       3
  46. #define STComSent    4
  47. #define STDataSent   5
  48. #define STErrSent    6
  49. #define STPacSent    7
  50. #define STComRate    8
  51. #define STDataRate   9
  52. #define STElapsed    10
  53.  
  54. #define STComRead    20
  55. #define STDataRead   21
  56. #define STErrRead    22
  57. #define STPacRead    23
  58. #define STUplSize    24
  59. #define STDowSize    25
  60. #define STUplRem     26
  61. #define STDowRem     27
  62. #define STRemTime    28
  63.  
  64. int  ST_Check_Abort()
  65. {
  66.     if ( kbhit() != 0 && getch() == '\x1B' )
  67.         return 1;
  68.     return 0;
  69. }
  70. void    ST_Yes_or_No(arg,yn)
  71. char    *arg;
  72. char    *yn;
  73. {
  74.     wrtstr(arg,17,20,0x02);
  75.     *yn = getch();
  76. }
  77. void    ST_Initialize()
  78. {
  79.     int    i;
  80.     char   tmp[160];
  81.     static char *menu[]={
  82.     "Msg     ","File    ","UpDow   ","Type    ","ComSent ",
  83.     "DataSent","ErrSent ","PacSent ","ComRate ","DataRate",
  84.     "Elapsed ",
  85.     "        ","        ","ComRead ","DataRead","ErrRead ",
  86.     "PacRead ","UplSize ","DowSize ","UplRem  ","DowRem  ",
  87.     "RemTime " };
  88.  
  89.     Dmy_form(tmp,50,0x98,0x95,0x99); 
  90.     wrtstr(tmp,15,7,0x06);
  91.  
  92.     Dmy_form(tmp,50,0x96,0x20,0x96); 
  93.     for ( i = 0 ; i < 13 ; i++ )
  94.         wrtstr(tmp,15,8+i,0x06);
  95.  
  96.     Dmy_form(tmp,50,0x9A,0x95,0x9B); 
  97.     wrtstr(tmp,15,21,0x06);
  98.  
  99.     wrtstr("  <<< B Plus Protocol(SM) Abort Hit ESC Key >>>",17,8,0x02);
  100.  
  101.     for ( i = 0 ; i < 22 ; i++ )
  102.     wrtstr(menu[i],17+(i/11)*24,9+(i%11),0x06);
  103. }
  104. void    ST_Terminate()
  105. {
  106.     Dsp_vram(cvram);
  107. }
  108. void    ST_Display_String(no,str)
  109. int    no;
  110. char    *str;
  111. {
  112.     wrtstr(str,27+(no/18)*24,9+(no%18),0x06);
  113. }
  114. void    ST_Display_Value(no,val)
  115. int    no;
  116. long    val;
  117. {
  118.     char     tmp[20];
  119.  
  120.     if ( no == STElapsed || no == STRemTime ) {
  121.     if ( val >= 3600 )
  122.         sprintf(tmp,"%2ld:%02ld:%02ld",val/3600,(val%3600)/60,val%60);
  123.     else if ( val >= 60 )
  124.         sprintf(tmp,"   %2ld:%02ld",val/60,val%60);
  125.     else
  126.         sprintf(tmp,"      %2ld",val);
  127.     } else
  128.     sprintf(tmp,"%8ld",val);
  129.     ST_Display_String(no,tmp);
  130. }
  131.  
  132. #define    Def_BS        4        /* Buffer size 128 x n */
  133. #define Max_SA             2           /* Maximum number of waiting Packets */
  134. #define Max_Buf_Size       (Def_BS*128+8) /* Largest data block we can handle */
  135.  
  136. #define Def_Buf_Size    511         /* Default data block               */
  137. #define Def_WS          1           /* I can send 2 Packets ahead       */
  138. #define Def_WR          1           /* I can receive single send-ahead  */
  139. #define Def_CM          1           /* I can handle CRC                 */
  140. #define Def_DQ          1           /* I can handle non-quoted NUL      */
  141.                                     /* (including the `Tf' Packet       */
  142. #define Def_UR          0           /* I can NOT handle Upload Recovery */
  143. #define Def_FI          1           /* I can handle File Information */
  144.  
  145. #define max_Errors         10
  146.  
  147. #define    bps110        0
  148. #define    bps150        1
  149. #define    bps300        2
  150. #define    bps600        3
  151. #define    bps1200        4
  152. #define    bps1800        5
  153. #define    bps2400        6
  154. #define    bps4800        7
  155. #define    bps9600        8
  156.  
  157. /* Receive States */
  158.  
  159. #define   R_Get_DLE       0
  160. #define   R_Get_B         1
  161. #define   R_Get_Seq       2
  162. #define   R_Get_Data      3
  163. #define   R_Get_Check     4
  164. #define   R_Send_ACK      5
  165. #define   R_Timed_Out     6
  166. #define   R_Success       7
  167.  
  168. /* Send States */
  169.  
  170. #define   S_Get_DLE       1
  171. #define   S_Get_Num       2
  172. #define   S_Have_ACK      3
  173. #define   S_Get_Packet    4
  174. #define   S_Skip_Packet   5
  175. #define   S_Timed_Out     6
  176. #define   S_Send_NAK      7
  177. #define   S_Send_ENQ      8
  178. #define   S_Send_Data     9
  179.  
  180. /* Other Constants */
  181.  
  182. #define   dle   16
  183. #define   etx   03
  184. #define   nak   21
  185. #define   enq   05
  186.  
  187. typedef struct {
  188.     int    seq;            /* Packet's sequence number  */
  189.     int    num;            /* Number of bytes in Packet */
  190.     char    buf[Max_Buf_Size];     /* Actual Packet data        */
  191.     } buf_type;
  192.  
  193. static    time_t    e_timer;
  194. static    int     BP_Auto_Resume = TRUE;
  195. static    int    BP_Use_File_Size = FALSE;
  196. static    long    BP_File_Size=0L;
  197. static    int    PortBps = bps2400;
  198. static    int    seq_num;
  199. static    UNSIG    checksum;
  200. static  char       His_WS,His_WR,His_BS,His_CM;
  201. static    char    His_QS[8];
  202. static    char    His_DR,His_UR,His_FI;
  203. static    char    Our_WS,Our_WR,Our_BS,Our_CM;
  204. static    char    Our_QS[8];
  205. static    char    Our_DR,Our_UR,Our_FI,Def_DR;
  206. static    int    Port_Update_Rate;
  207. static    int    B_Plus;
  208. static    int    Use_CRC;
  209. static    int    BP_Special_Quoting = 0;
  210. static    int    Buffer_Size;
  211. static    int    SA_Max;
  212. static    int    SA_Error_Count;
  213. static    char    Quote_Table[256];
  214. static    char    BP_Special_Quote_Set[]={
  215.             0x14, 0x00, 0xd4, 0x00,
  216.             0x00, 0x00, 0x00, 0x00 };
  217. static    char    DQ_Full[]={
  218.             0xff, 0xff, 0xff, 0xff,
  219.                0xff, 0xff, 0xff, 0xff };
  220. static    char    DQ_Default[]={
  221.                 0x14, 0x00, 0xd4, 0x00,
  222.                  0x00, 0x00, 0x00, 0x00 };
  223. static    char    DQ_Minimal[]={
  224.                 0x14, 0x00, 0xd4, 0x00,
  225.                 0x00, 0x00, 0x00, 0x00 };
  226. static    char    DQ_Extended[]={
  227.             0x14, 0x00, 0xd4, 0x00,
  228.                 0x00, 0x00, 0x50, 0x00 };
  229.  
  230. static    int     R_Size,ch;
  231. static    int     Timed_Out,Packet_Received,masked;
  232. static    buf_type SA_Buf[Max_SA+1];
  233. static    int     SA_Next_to_ACK;
  234. static    int     SA_Next_to_Fill;
  235. static    int     SA_Waiting;
  236. static    int        Aborting;
  237. static    char    R_buffer[Max_Buf_Size];
  238. static    char    filename[256];
  239. static    int     S_Counter;
  240. static    int     R_Counter;
  241. static    long    S_Com_Data;
  242. static    long    R_Com_Data;
  243. static    long    S_File_Data;
  244. static  long    R_File_Data;
  245. static    long    S_Packet_Count;
  246. static    long    R_Packet_Count;
  247. static    long    S_Error_Count;
  248. static    long    R_Error_Count;
  249. static    long    S_File_Size;
  250. static    long    R_File_Size;
  251. static    long    S_Remaining;
  252. static    long    R_Remaining;
  253. static    long    Com_Rate;
  254. static    long    Data_Rate;
  255. static    long    Time_Estimate;
  256. static    int    Resume_Flag;
  257. static    UNSIG    crc_16;
  258. static    char    Val_Str[50];
  259. static    int    e_i, e_j, e_n;
  260.  
  261. UNSIG    crc_table[] = {
  262.         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
  263.         0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
  264.         0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
  265.         0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
  266.         0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
  267.         0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
  268.         0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
  269.         0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
  270.         0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
  271.         0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
  272.         0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
  273.         0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
  274.         0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
  275.     0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
  276.         0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
  277.         0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
  278.         0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
  279.         0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
  280.         0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
  281.         0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
  282.         0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
  283.         0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  284.         0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
  285.         0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
  286.         0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
  287.         0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
  288.         0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
  289.         0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
  290.         0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
  291.         0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
  292.         0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
  293.         0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
  294.     };
  295.  
  296. void    ltoa( n, s )
  297. long    n;
  298. char    *s;
  299. {
  300.     char   *t;
  301.     long   i;
  302.     char   c;
  303.     long   sign;
  304.     long   divten;
  305.  
  306.     if ( (sign = n) < 0 )
  307.         n = -n;
  308.  
  309.     t = s;
  310.     do {
  311.         i = (divten = (n / 10)) * 10;
  312.     *(t++) = ( n - i ) + '0';
  313.     } while( (n = divten) > 0 );
  314.  
  315.     if( sign < 0 )
  316.         *(t++) = '-';
  317.  
  318.     *t = '\0';
  319.     t--;
  320.  
  321.     while( s < t ) {
  322.     c = *t;
  323.     *(t--) = *s;
  324.     *(s++) = c;
  325.     }
  326. }
  327. static void Clear_Quote_Table()
  328. {
  329.     memset(Quote_Table,0,256);
  330. }
  331. static void Update_Quote_Table (Quote_Set)
  332. char    *Quote_Set;
  333. {
  334.     int       i, j, k;
  335.     char   b, c;
  336.  
  337.     c = 0x40;
  338.     k = 0x00;
  339.  
  340.     for ( i = 0 ; i < 8 ; i++ ) {
  341.     if ( i == 4 ) {
  342.         c = 0x60;
  343.         k = 0x80;
  344.     }
  345.  
  346.     b = Quote_Set[i];
  347.  
  348.     for ( j = 0 ; j < 8 ; j++ ) {
  349.         if ( (b & 0x80) != 0)
  350.         Quote_Table[k] = c;
  351.  
  352.         b <<= 1;
  353.         c++;
  354.         k++;
  355.     }
  356.     }
  357. }
  358.  
  359. void    BP_Quote_This (Value)
  360. int    Value;
  361. {
  362.     int     i, j;
  363.  
  364.     if ( (Value >= 0x00 && Value <= 0x1F) ||
  365.      (Value >= 0x80 && Value <= 0x9f) ) {
  366.  
  367.     if ( Value > 0x1f ) {
  368.         i = 4;
  369.             Value = Value & 0x1f;
  370.     } else
  371.         i = 0;
  372.  
  373.     i = i + Value / 8;
  374.     j = Value % 8;
  375.     BP_Special_Quote_Set[i] |= (0x80 >> j);
  376.     BP_Special_Quoting = TRUE;
  377.  
  378.     } else if ( Value == (-1) ) {
  379.  
  380.     for( i=0 ; i < sizeof(DQ_Minimal) ; i++ )
  381.         BP_Special_Quote_Set[i] = DQ_Minimal[i];
  382.  
  383.     BP_Special_Quoting = FALSE;
  384.     }
  385. }
  386.  
  387. void    BP_Term_ENQ()
  388. {
  389.     int     i;
  390.  
  391.     seq_num = 0;
  392.     Buffer_Size = 512;               /* Set up defaults */
  393.     Our_WS = 0;
  394.     Our_WR = 0;
  395.     Our_BS = 4;
  396.     Our_CM = 0;
  397.     Our_DR = 0;
  398.     Our_UR = 0;
  399.     Our_FI = 0;
  400.  
  401.     B_Plus      = FALSE;             /* Not B Plus Protocol */
  402.     Use_CRC     = FALSE;             /* Not CRC_16      */
  403.     SA_Max      = 1;                 /* Single Packet send */
  404.     SA_Error_Count = 0;              /* No Upload errors yet */
  405.  
  406.     for( i = 0 ; i < sizeof(DQ_Minimal) ; i++ )
  407.     Our_QS[i] = DQ_Minimal[i];
  408.  
  409.     Clear_Quote_Table();
  410.     Update_Quote_Table(Our_QS);
  411.  
  412.     Async_Send(dle);
  413.     Async_Send('+');
  414.     Async_Send('+');
  415.     Async_Send(dle);
  416.     Async_Send('0');
  417. }
  418.  
  419. void    BP_Term_ESC_I(esc_I_Res)
  420. char    esc_I_Res[];
  421. {
  422.     int        i;
  423.     char    t[256];
  424.     int        cks;
  425.  
  426.     cks = 0;
  427.  
  428.     for ( i = 0 ; i < strlen(esc_I_Res) ; i++ ) {
  429.       Async_Send(esc_I_Res[i]);
  430.     cks += esc_I_Res[i];
  431.     }
  432.  
  433.     Async_Send (',');
  434.     Async_Send ('+');
  435.     cks = cks + ',' + '+';
  436.  
  437.     ltoa( (long)cks, t );
  438.  
  439.     i = 4 - strlen( t );
  440.     while( i-- )
  441.     Async_Send( '0' );
  442.  
  443.     for ( i = 0 ; i < strlen(t) ; i++ )
  444.     Async_Send(t[i]);
  445.  
  446.     Async_Send(0x0d);
  447. }
  448.  
  449. static    int    Init_CRC (value)
  450. int    value;
  451. {
  452.     return( crc_16 = value );
  453. }
  454. static    UNSIG    Upd_CRC (value)
  455. UNSIG    value;
  456. {
  457.     value &= 0xFF;
  458.     crc_16 = crc_table [((crc_16 >> 8) ^ (value)) & 0xff] ^ (crc_16 << 8);
  459.     return( crc_16 );
  460. }
  461. static    void do_checksum (c)
  462. int    c;
  463. {
  464.     c &= 0xFF;
  465.     if ( B_Plus && Use_CRC )
  466.         checksum = Upd_CRC (c);
  467.     else {
  468.            checksum <<= 1;
  469.     if (checksum > 255)
  470.             checksum = (checksum & 0xff) + 1;
  471.     checksum += c;
  472.     if (checksum > 255)
  473.             checksum = (checksum & 0xff) + 1;
  474.     }
  475. }
  476. static    void    send_count()
  477. {
  478.     S_Com_Data++;
  479.     if ( (S_Counter++) >= Port_Update_Rate ) {
  480.     S_Counter = 0;
  481.         ST_Display_Value (STComSent, S_Com_Data);
  482.     }
  483. }
  484. static    void send_byte (ch)
  485. char   ch;
  486. {
  487.     Async_Send (ch);
  488.     send_count();
  489. }
  490. static    void buf_send_byte (ch)
  491. char   ch;
  492. {
  493.     Bufferd_Send(ch);
  494.     send_count();
  495. }
  496. static void send_masked_byte (ch)
  497. int    ch;
  498. {
  499.     ch &= 0xff;
  500.  
  501.     if (Quote_Table [ch] != 0) {
  502.         buf_send_byte(dle);
  503.     buf_send_byte(Quote_Table[ch]);
  504.     } else
  505.     buf_send_byte(ch);
  506. }
  507. static void Send_ACK()
  508. {
  509.     send_byte(dle);
  510.     send_byte(seq_num + '0');
  511. }
  512. static void Send_NAK()
  513. {
  514.     send_byte(nak);
  515. }
  516. static void Send_ENQ()
  517. {
  518.     send_byte(enq);
  519. }
  520. static int read_byte()
  521. {
  522.     int     chx;
  523.     int     Hiber;
  524.     time_t  start,now;
  525.  
  526.     Timed_Out = FALSE;
  527.  
  528.     if ( (chx = Bufferd_Recive()) != ERR )
  529.     goto ENDOF;
  530.  
  531.     time(&start);
  532.  
  533.     if ( !Aborting )
  534.     Hiber = 10;
  535.     else
  536.     Hiber = 5;
  537.  
  538.     while ( (chx = Bufferd_Recive()) == ERR ) {
  539.         time(&now);
  540.     if ( (now - start) >= Hiber ) {
  541.         Timed_Out = TRUE;
  542.         return( FALSE );
  543.     }
  544.     }
  545.  
  546. ENDOF:
  547.     ch = chx;
  548.     R_Com_Data++;
  549.     if ( (R_Counter++) >= Port_Update_Rate ) {
  550.     R_Counter = 0;
  551.     ST_Display_Value(STComRead, R_Com_Data);
  552.     }
  553.     return(TRUE);
  554. }
  555. static int read_masked_byte()
  556. {
  557.     masked = FALSE;
  558.  
  559.     if ( read_byte() == FALSE )
  560.         return(FALSE);
  561.  
  562.     if ( ch == dle ) {
  563.     if (read_byte() == FALSE)
  564.             return(FALSE);
  565.     if ( ch < 0x60 )
  566.         ch &= 0x1f;
  567.     else
  568.         ch = (ch & 0x1F) | 0x80;
  569.     masked = TRUE;
  570.     }
  571.     return(TRUE);
  572. }
  573. static    int Incr_Seq (value)
  574. int    value;
  575. {
  576.     if ( value == 9 )
  577.     return( 0);
  578.     else
  579.     return(value + 1);
  580. }
  581. static    int    Read_Packet (Lead_in_Seen, From_Send_Packet)
  582. int    Lead_in_Seen;
  583. int    From_Send_Packet;
  584. {
  585.     int        State,
  586.         next_seq,
  587.         block_num,
  588.         errors,
  589.         new_cks;
  590.     int        i;
  591.     int        NAK_Sent;
  592.  
  593.     if ( Packet_Received ) {
  594.     Packet_Received = FALSE;
  595.     return( TRUE);
  596.     }
  597.  
  598.     NAK_Sent = FALSE;
  599.     memset(R_buffer,0,Buffer_Size);
  600.     next_seq = (seq_num +  1) % 10;
  601.     errors = 0;
  602.     i = 0;
  603.  
  604.     if ( Lead_in_Seen )
  605.     State = R_Get_Seq;
  606.     else
  607.     State = R_Get_DLE;
  608.  
  609.     while( TRUE ) {
  610.     switch ( State ) {
  611.     case R_Get_DLE :
  612.         if ( ST_Check_Abort() && !Aborting ) {
  613.         ST_Display_String(STMsg,"Aborting download per your request");
  614.             Send_Failure ("AAborted by user");
  615.         return(FALSE);
  616.         }
  617.         if ( !read_byte() )
  618.         State = R_Timed_Out;
  619.         else if ((ch & 0x7F) == dle )
  620.         State = R_Get_B;
  621.         else if ((ch & 0x7F) == enq )
  622.         State = R_Send_ACK;
  623.         break;
  624.  
  625.     case R_Get_B :
  626.         if ( !read_byte() )
  627.         State = R_Timed_Out;
  628.         else if ((ch & 0x7F) == 'B')
  629.         State = R_Get_Seq;
  630.         else if (ch == enq)
  631.         State = R_Send_ACK;
  632.         else if (ch == ';') {
  633.         ST_Display_Value (STComRead, R_Com_Data);
  634.         State = R_Get_DLE;
  635.         } else
  636.         State = R_Get_DLE;
  637.         break;
  638.  
  639.     case R_Get_Seq :
  640.         if ( Resume_Flag ) {
  641.         time(&e_timer);
  642.         R_Com_Data = 2;
  643.         }
  644.         if ( !read_byte() )
  645.         State = R_Timed_Out;
  646.         else if ( ch == enq)
  647.         State = R_Send_ACK;
  648.         else {
  649.         if (B_Plus && Use_CRC)
  650.             checksum = Init_CRC(0xffff);
  651.         else
  652.             checksum = 0;
  653.         block_num = ch - '0';
  654.         do_checksum (ch);
  655.         i = 0;
  656.         State = R_Get_Data;
  657.         }
  658.         break;
  659.  
  660.     case R_Get_Data :
  661.         if ( !read_masked_byte() )
  662.         State = R_Timed_Out;
  663.         else if ( (ch == etx) && !masked ) {
  664.         do_checksum (etx);
  665.         State = R_Get_Check;
  666.         } else {
  667.         if ( i < Max_Buf_Size ) {
  668.             R_buffer[i] = ch;
  669.             i++;
  670.             do_checksum (ch);
  671.         }
  672.         }
  673.         break;
  674.  
  675.     case R_Get_Check :
  676.         if ( !read_masked_byte() )
  677.         State = R_Timed_Out;
  678.         else {
  679.         if ( B_Plus && Use_CRC ) {
  680.             checksum = Upd_CRC(ch);
  681.             if ( !read_masked_byte() )
  682.             new_cks = checksum ^ 0xff;
  683.             else {
  684.             checksum = Upd_CRC(ch);
  685.             new_cks = 0;
  686.                 }
  687.         } else
  688.             new_cks = ch;
  689.  
  690.         if (new_cks != checksum) {
  691.             ST_Display_String(STMsg,"CRC No Match!");
  692.             State = R_Timed_Out;
  693.         } else if (R_buffer[0] == 'F') /* Watch for Failure Packet */
  694.             State = R_Success;     /* which is accepted regardless */
  695.         else if (block_num == seq_num) /* Watch for duplicate block */
  696.             State = R_Send_ACK; /* Simply ACK it */
  697.         else if (block_num != next_seq)
  698.             State = R_Timed_Out; /* Bad seq num */
  699.         else
  700.             State = R_Success;
  701.         }
  702.         break;
  703.  
  704.     case R_Timed_Out :
  705.         errors++;
  706.         if ( (errors > max_Errors) || (From_Send_Packet) )
  707.         return( FALSE );
  708.         if ( !NAK_Sent || !B_Plus ) {
  709.         R_Error_Count++;
  710.         ST_Display_Value (STErrRead, R_Error_Count);
  711.         NAK_Sent = TRUE;
  712.         Send_NAK();
  713.         }
  714.         State = R_Get_DLE;
  715.         break;
  716.  
  717.     case R_Send_ACK :
  718.         if ( !Aborting )
  719.         Send_ACK();
  720.         State = R_Get_DLE;        /* wait for the next block */
  721.             break;
  722.  
  723.     case R_Success :
  724.         ST_Display_Value (STComRead, R_Com_Data);
  725.         ST_Display_Value (STComSent, S_Com_Data);
  726.         if ( !Aborting )
  727.         seq_num = block_num;
  728.         R_Size = i;
  729.         R_Packet_Count++;
  730.         ST_Display_Value (STPacRead, R_Packet_Count);
  731.         return(TRUE);
  732.         break;
  733.  
  734.     }
  735.     }
  736.  
  737. } /* Read_Packet */
  738.  
  739. static    void Send_Data (BuffeR_Number)
  740. int    BuffeR_Number;
  741. {
  742.     int        i;
  743.     buf_type *p;
  744.  
  745.     p = &SA_Buf[BuffeR_Number];
  746.  
  747.     if (B_Plus && Use_CRC)
  748.     checksum = Init_CRC (0xffff);
  749.     else
  750.     checksum = 0;
  751.  
  752.     buf_send_byte (dle);
  753.     buf_send_byte ('B');
  754.     buf_send_byte (p->seq + '0');
  755.     do_checksum (p->seq + '0');
  756.  
  757.     for (i = 0; i <= p->num; i++ ) {
  758.     send_masked_byte (p->buf [i]);
  759.     do_checksum (p->buf[i]);
  760.     }
  761.  
  762.     buf_send_byte (etx);
  763.     do_checksum (etx);
  764.  
  765.     if (B_Plus && Use_CRC)
  766.     send_masked_byte (checksum >> 8);
  767.  
  768.     send_masked_byte (checksum);
  769.  
  770.     Bufferd_Flush();
  771. }
  772. static    int    Incr_SA (Old_Value)
  773. int    Old_Value;
  774. {
  775.     if (Old_Value == Max_SA)
  776.     return(0);
  777.     else
  778.     return(Old_Value + 1);
  779. }
  780.  
  781. #define      Get_First_DLE     1
  782. #define      Get_First_Digit   2
  783. #define      Get_Second_DLE    3
  784. #define      Get_Second_Digit  4
  785.  
  786. static    int    ReSync()
  787. {
  788.     int        State,Digit_1;
  789.  
  790.     send_byte (enq);     /* Send <ENQ><ENQ> */
  791.     send_byte (enq);
  792.     State = Get_First_DLE;
  793.  
  794.     while(1) {
  795.     switch (State) {
  796.  
  797.     case Get_First_DLE :
  798.         if ( !read_byte() )
  799.         return(-1);
  800.         if ( ch == dle )
  801.         State = Get_First_Digit;
  802.         break;
  803.  
  804.     case Get_First_Digit :
  805.         if ( !read_byte() )
  806.         return(-1);
  807.         if ( (ch >= '0') && (ch <= '9') ) {
  808.         Digit_1 = ch;
  809.         State = Get_Second_DLE;
  810.         } else if (ch == 'B')
  811.         return( ch );
  812.         break;
  813.  
  814.     case Get_Second_DLE :
  815.         if ( !read_byte() )
  816.         return(-1);
  817.         if ( ch == dle )
  818.         State = Get_Second_Digit;
  819.         break;
  820.  
  821.     case Get_Second_Digit :
  822.         if ( !read_byte() )
  823.         return(-1);
  824.         if ( (ch >= '0') && (ch <= '9') ) {
  825.         if (Digit_1 == ch  )
  826.             return(ch);
  827.         else if (ch == 'B')
  828.             return( ch );
  829.         else {
  830.             Digit_1 = ch;
  831.             State = Get_Second_DLE;
  832.          }
  833.         } else
  834.         State = Get_Second_DLE;
  835.         break;
  836.  
  837.     } /* case */
  838.     }  /* while TRUE */
  839. }
  840.  
  841. static    int    Get_ACK()
  842. {
  843.     int        State,
  844.         errors,
  845.         block_num,
  846.         i;
  847.     int        Sent_ENQ;
  848.     int        SA_Index;
  849.  
  850.     Packet_Received = FALSE;
  851.     errors = 0;
  852.     Sent_ENQ = FALSE;
  853.     State = S_Get_DLE;
  854.  
  855.     while ( 1 ) {
  856.     switch (State) {
  857.     case S_Get_DLE :
  858.         if ( ST_Check_Abort() && !Aborting ) {
  859.         ST_Display_String (STMsg,
  860.                 "Aborting the upload per your request");
  861.         Send_Failure ("AAborted by user");
  862.         return(FALSE);
  863.         }
  864.         if ( !read_byte() )
  865.         State = S_Timed_Out;
  866.         else {
  867.         if ( ch == dle )
  868.             State = S_Get_Num;
  869.         else if (ch == nak )
  870.             State = S_Send_ENQ;
  871.         else if (ch == etx )
  872.             State = S_Send_NAK;
  873.         }
  874.         break;
  875.  
  876.     case S_Get_Num :
  877.         if (!read_byte() )
  878.         State = S_Timed_Out;
  879.         else if ( (ch >= '0') && (ch <= '9') )
  880.         State = S_Have_ACK;           /* Received ACK */
  881.         else if ( ch == 'B' ) {
  882.         if (!Aborting)
  883.             State = S_Get_Packet; /* Try to receive a Packet */
  884.         else
  885.             State = S_Skip_Packet;   /* Try to skip a Packet */
  886.         } else if (ch == nak)
  887.         State = S_Send_ENQ;
  888.         else if (ch == ';') {
  889.         ST_Display_Value (STComRead, R_Com_Data);
  890.         State = S_Get_DLE;
  891.         } else
  892.         State = S_Timed_Out;
  893.         break;
  894.  
  895.     case S_Get_Packet :
  896.         if (Read_Packet (TRUE, TRUE) ) {
  897.         Packet_Received = TRUE;
  898.         if (R_buffer [0] == 'F') {
  899.             Send_ACK();
  900.             return(FALSE);
  901.         }
  902.         State = S_Get_DLE;     /* Stay here to find the ACK */
  903.         } else
  904.         State = S_Get_DLE;
  905.         break;
  906.  
  907.     case S_Skip_Packet :    /* Skip an incoming Packet */
  908.         if (!read_byte())
  909.         State = S_Timed_Out;
  910.         else if (ch == etx ) {
  911.         if (!read_masked_byte())
  912.             State = S_Timed_Out;
  913.         else if (!Use_CRC)
  914.             State = S_Get_DLE;
  915.         else if (!read_masked_byte())
  916.             State = S_Timed_Out;
  917.         else
  918.             State = S_Get_DLE;
  919.         }
  920.         break;
  921.  
  922.     case S_Have_ACK :
  923.         block_num = ch - '0';
  924.         ST_Display_Value (STComSent, S_Com_Data);
  925.         ST_Display_Value (STComRead, R_Com_Data);
  926.  
  927.         if ( SA_Buf[SA_Next_to_ACK].seq == block_num  ) {
  928.         SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
  929.         SA_Waiting = SA_Waiting - 1;
  930.  
  931.         if (SA_Error_Count > 0 )
  932.                     SA_Error_Count--;
  933.         return(TRUE);
  934.         } else if ( (SA_Buf[Incr_SA(SA_Next_to_ACK)].seq == block_num) &&
  935.              SA_Waiting == 2) {
  936.         SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
  937.         SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
  938.         SA_Waiting = SA_Waiting - 2;
  939.         if (SA_Error_Count > 0)
  940.             SA_Error_Count--;
  941.          return(TRUE);
  942.  
  943.         } else if ( SA_Buf[SA_Next_to_ACK].seq == Incr_Seq(block_num) ) {
  944.         if ( Sent_ENQ )
  945.             State = S_Send_Data; /* Remote missed first block */
  946.         else
  947.             State = S_Get_DLE;       /* Duplicate ACK */
  948.         } else {
  949.         if ( !Aborting )        /* While aborting, ignore any */
  950.             State = S_Timed_Out; /* ACKs that have been sent   */
  951.         else
  952.             State = S_Get_DLE;    /* which are not for the failure */
  953.         }                                       /* Packet. */
  954.         Sent_ENQ = FALSE;
  955.         break;
  956.  
  957.     case S_Timed_Out :
  958.         State = S_Send_ENQ;
  959.         break;
  960.  
  961.     case S_Send_NAK :
  962.         errors++;
  963.         S_Error_Count++;
  964.         ST_Display_Value (STErrSent, S_Error_Count);
  965.         if (errors > max_Errors)
  966.         return(FALSE);
  967.         Send_NAK();
  968.         State = S_Get_DLE;
  969.         break;
  970.  
  971.     case S_Send_ENQ :
  972.         errors++;
  973.         S_Error_Count++;
  974.         ST_Display_Value (STErrSent, S_Error_Count);
  975.         if ( (errors > max_Errors) || (Aborting && (errors > 3)) )
  976.         return(FALSE);
  977.         ch = ReSync();
  978.         if ( ch == (-1) )
  979.         State = S_Get_DLE;
  980.         else if (ch == 'B') {
  981.         if( !Aborting )
  982.             State = S_Get_Packet;   /* Try to receive a Packet */
  983.         else
  984.             State = S_Skip_Packet;  /* Try to skip a Packet */
  985.         } else
  986.         State = S_Have_ACK;
  987.         Sent_ENQ   = TRUE;
  988.         break;
  989.  
  990.     case S_Send_Data :
  991.         SA_Error_Count += 3;
  992.         if (SA_Error_Count >= 12) /* Stop Upload Send Ahead if too many */
  993.         SA_Max = 1;           /* errors have occured */
  994.         SA_Index = SA_Next_to_ACK;
  995.         for ( i = 1 ; i <= SA_Waiting ; i++ ) {
  996.         Send_Data (SA_Index);
  997.                SA_Index = Incr_SA (SA_Index);
  998.         }
  999.         State = S_Get_DLE;
  1000.         Sent_ENQ = FALSE;
  1001.         break;
  1002.     }
  1003.    }
  1004. } /* Get_ACK */
  1005.  
  1006. static    int    send_Packet (size)
  1007. int    size;
  1008. {
  1009.     while ( SA_Waiting >= SA_Max ) {
  1010.     if ( !Get_ACK() )
  1011.         return(FALSE);
  1012.     }
  1013.  
  1014.     seq_num = Incr_Seq (seq_num);
  1015.     SA_Buf [SA_Next_to_Fill].seq = seq_num;
  1016.     SA_Buf [SA_Next_to_Fill].num = size;
  1017.     Send_Data (SA_Next_to_Fill);
  1018.     SA_Next_to_Fill = Incr_SA (SA_Next_to_Fill);
  1019.     SA_Waiting = SA_Waiting + 1;
  1020.     S_Packet_Count++;
  1021.     ST_Display_Value (STComSent, S_Com_Data);
  1022.     ST_Display_Value (STPacSent, S_Packet_Count);
  1023.     return(TRUE);
  1024. }
  1025.  
  1026. static    int    SA_Flush()
  1027. {
  1028.     while ( SA_Waiting > 0 ) {
  1029.     if ( !Get_ACK() )
  1030.         return(FALSE);
  1031.     }
  1032.     return( TRUE );
  1033. }
  1034.  
  1035. static    void Send_Failure (Reason)
  1036. char    Reason[];
  1037. {
  1038.     int        i;
  1039.     buf_type *p;
  1040.  
  1041.     SA_Next_to_ACK = 0;
  1042.     SA_Next_to_Fill = 0;
  1043.     SA_Waiting = 0;
  1044.     Aborting   = TRUE;          /* Inform Get_ACK we're aborting ]*/
  1045.  
  1046.     p = &SA_Buf [0];
  1047.     p->buf [0] = 'F';
  1048.     for ( i = 1 ; i <= strlen(Reason) ; i++ )
  1049.     p->buf [i] = (Reason [i]);
  1050.  
  1051.     if ( send_Packet (strlen(Reason)) )
  1052.     SA_Flush();   /* Gotta wait for the Initiator to ACK it */
  1053. }
  1054.  
  1055. static    int    Send_File (name)
  1056. char    name[];
  1057. {
  1058.     int        n;
  1059.     FILE    *data_File;
  1060.     buf_type *p;
  1061.     time_t now;
  1062.  
  1063.     data_File = fopen (name,READ_OP);
  1064.  
  1065.     if ( data_File == 0 ) {
  1066.     ST_Display_String (STMsg, "Cannot find that file");
  1067.     Send_Failure ("MFile not found");
  1068.     return(FALSE);
  1069.     }
  1070.  
  1071.     fseek(data_File,0L,2);          /* seek to end of file */
  1072.     S_Remaining = ftell(data_File); /* how long is this file ? */
  1073.     fseek(data_File,0L,0);          /* back to the start, ready to go */
  1074.     ST_Display_Value (STUplRem, S_Remaining);
  1075.  
  1076.     S_Com_Data = 0;
  1077.     R_Com_Data = 0;
  1078.     time(&e_timer);
  1079.  
  1080.     do {
  1081.     p = &SA_Buf [SA_Next_to_Fill];
  1082.     p->buf [0] = 'N';
  1083.     n = fread (&p->buf[1], 1, Buffer_Size, data_File);
  1084.  
  1085.     if ( n > 0 ) {
  1086.         if (send_Packet (n) == FALSE) {
  1087.         fclose(data_File);
  1088.         return(FALSE);
  1089.         }
  1090.  
  1091.         S_File_Data = S_File_Data +  (n);
  1092.         S_File_Size = S_File_Size +  (n);
  1093.         S_Remaining = S_Remaining -  (n);
  1094.         ST_Display_Value (STUplSize, S_File_Size);
  1095.         ST_Display_Value (STDataSent, S_File_Data);
  1096.         ST_Display_Value (STUplRem, S_Remaining);
  1097.         time(&now);
  1098.         Time_Estimate = now - e_timer;
  1099.         ST_Display_Value (STElapsed, Time_Estimate);
  1100.  
  1101.         if ( Time_Estimate != 0 ) {
  1102.         Com_Rate = S_Com_Data / Time_Estimate;
  1103.         Data_Rate = S_File_Data / Time_Estimate;
  1104.         ST_Display_Value (STComRate, Com_Rate);
  1105.         ST_Display_Value (STDataRate, Data_Rate);
  1106.  
  1107.         if ( Data_Rate != 0 ) {
  1108.             Time_Estimate = S_Remaining / Data_Rate;
  1109.             ST_Display_Value (STRemTime, Time_Estimate);
  1110.                }
  1111.         }
  1112.     }
  1113.     } while(n > 0);
  1114.  
  1115.     if ( ferror(data_File) != 0) {
  1116.     Send_Failure ("EFile read failure");
  1117.     ST_Display_String (STMsg, "Read failure...aborting");
  1118.     fclose(data_File);
  1119.     return(FALSE);
  1120.     }
  1121.  
  1122.     p = &SA_Buf [SA_Next_to_Fill];
  1123.     p->buf [0] = 'T';
  1124.     p->buf [1] = 'C';
  1125.  
  1126.     if ( send_Packet (2) == FALSE ) {
  1127.     fclose (data_File);
  1128.     return(FALSE);
  1129.     } else {
  1130.     fclose (data_File);
  1131.     if (!SA_Flush())
  1132.         return(FALSE);
  1133.     return(TRUE);
  1134.     }
  1135.  
  1136. } /* Send_File */
  1137.  
  1138. static    void Do_Transport_Parameters()
  1139. {
  1140.     int        Quote_Set_Present;
  1141.     int     i;
  1142.     buf_type *p;
  1143.  
  1144.     if (BP_Special_Quoting) {
  1145.     for ( i = 0 ; i < 8 ; i++ )
  1146.         Our_QS[i] = BP_Special_Quote_Set[i];
  1147.     } else {
  1148.     for ( i = 0 ; i < 8 ; i++ )
  1149.         Our_QS[i] = DQ_Minimal[i];
  1150.     }
  1151.  
  1152.     for ( i = R_Size + 1; i<=512; i++ )
  1153.     R_buffer [i] = 0;
  1154.  
  1155.     His_WS = R_buffer [1];     /* Pick out Initiator's parameters */
  1156.     His_WR = R_buffer [2];
  1157.     His_BS = R_buffer [3];
  1158.     His_CM = R_buffer [4];
  1159.  
  1160.     His_QS [0] = R_buffer [7];
  1161.     His_QS [1] = R_buffer [8];
  1162.     His_QS [2] = R_buffer [9];
  1163.     His_QS [3] = R_buffer [10];
  1164.     His_QS [4] = R_buffer [11];
  1165.     His_QS [5] = R_buffer [12];
  1166.     His_QS [6] = R_buffer [13];
  1167.     His_QS [7] = R_buffer [14];
  1168.  
  1169.     His_DR = R_buffer [15];
  1170.     His_UR = R_buffer [16];
  1171.     His_FI = R_buffer [17];
  1172.  
  1173.     Quote_Set_Present = (R_Size >= 14 ? TRUE:FALSE);
  1174.  
  1175.     p = &(SA_Buf[SA_Next_to_Fill]);
  1176.     p->buf [0] = '+';  /* Prepare to return Our own parameters */
  1177.     p->buf [1] = Def_WS;
  1178.     p->buf [2] = Def_WR;
  1179.     p->buf [3] = Def_BS;
  1180.     p->buf [4] = Def_CM;
  1181.     p->buf [5] = Def_DQ;
  1182.     p->buf [6] = 0;          /* No transport layer here */
  1183.  
  1184.     for ( i = 0 ; i <= 7 ; i++ )
  1185.     p->buf[i + 7] = Our_QS[i];
  1186.  
  1187.     if ( BP_Auto_Resume )      /* Set Download Resume according to */
  1188.     Def_DR = 2;       /* user's preference */
  1189.     else
  1190.     Def_DR = 1;
  1191.  
  1192.     p->buf [15] = Def_DR;
  1193.     p->buf [16] = Def_UR;
  1194.     p->buf [17] = Def_FI;
  1195.  
  1196.     Update_Quote_Table (DQ_Full);   /* Send the + Packet w/ full quoting */
  1197.  
  1198.     if ( !send_Packet(17) )
  1199.     return;
  1200.  
  1201.     if ( SA_Flush() ) {         /* Wait for host's ACK on Our Packet */
  1202.     Our_WR = His_WS < Def_WR ? His_WS:Def_WR;
  1203.     Our_WS = His_WR < Def_WS ? His_WR:Def_WS;
  1204.     Our_BS = His_BS < Def_BS ? His_BS:Def_BS;
  1205.     Our_CM = His_CM < Def_CM ? His_CM:Def_CM;
  1206.     Our_DR = His_DR < Def_DR ? His_DR:Def_DR;
  1207.     Our_UR = His_UR < Def_UR ? His_UR:Def_UR;
  1208.     Our_FI = His_FI < Def_FI ? His_FI:Def_FI;
  1209.     if (Our_BS == 0)
  1210.         Our_BS = 4;    /* Default */
  1211.  
  1212.     Buffer_Size = Our_BS * 128;
  1213.     B_Plus = TRUE;
  1214.  
  1215.     if (Our_CM == 1)
  1216.         Use_CRC = TRUE;
  1217.  
  1218.     if (Our_WS != 0)
  1219.         SA_Max = Max_SA;
  1220.     }
  1221.  
  1222.     Clear_Quote_Table();            /* Restore Our Quoting Set */
  1223.     Update_Quote_Table (Our_QS);
  1224.  
  1225.     if ( Quote_Set_Present )     /* Insert Initiator's Quote Set */
  1226.     Update_Quote_Table (His_QS);
  1227. }
  1228.  
  1229. static    void Check_Keep (data_File, Name)
  1230. FILE    *data_File;
  1231. char    Name[];
  1232. {
  1233.     char    yn;
  1234.     char    str[256];
  1235.  
  1236.     fclose (data_File);
  1237.  
  1238.     if ( (!BP_Auto_Resume) || (!B_Plus) || (Our_DR == 0) ) {
  1239.     strcpy( str, "Do you wish to retain the partial " );
  1240.     strcat( str, Name );
  1241.     strcat( str, "?" );
  1242.     ST_Yes_or_No( str, &yn );
  1243.     } else
  1244.     yn = 'Y';
  1245.  
  1246.     if ( yn == 'N' || yn == 'n' ) {
  1247.     unlink ( Name );
  1248.     ST_Display_String (STMsg, "File erased.");
  1249.     } else {
  1250.     ST_Display_String (STMsg, "File retained.");
  1251.     }
  1252. }
  1253.  
  1254. static void Extract_String()   /* Extract next string of characters */
  1255. {
  1256.     int        Digit_Seen;
  1257.  
  1258.     Digit_Seen = FALSE;
  1259.     e_j = 0;
  1260.  
  1261.     while ( e_i <= e_n ) {
  1262.     if ( (R_buffer [e_i] >= '0') && (R_buffer [e_i] <= '9') ) {
  1263.         Digit_Seen = TRUE;
  1264.         e_j++;
  1265.         Val_Str [e_j] = R_buffer [e_i];
  1266.     } else if ( Digit_Seen ) {
  1267.         Val_Str [0] = e_j;
  1268.         return;
  1269.     }
  1270.     e_i++;
  1271.     }
  1272. }
  1273.  
  1274. static    void Process_File_Information()
  1275. {
  1276.     int        i;
  1277.  
  1278.     e_n = R_Size - 1;
  1279.     e_i = 4;           /* Skip data type and compression flag */
  1280.     Extract_String();
  1281. /*  Val (Val_Str, R_Remaining, e_j); */
  1282.     R_Remaining = 0;
  1283.     for ( i = 1 ; i <= e_j ; i++ )
  1284.     R_Remaining = (R_Remaining * 10) + (Val_Str[i] - '0');
  1285.  
  1286.     R_Remaining = R_Remaining - R_File_Size;  /* Adjust for Dow Resume */
  1287.     ST_Display_Value (STDowRem, R_Remaining);
  1288.     S_Packet_Count = 0;
  1289.     R_Packet_Count = 0;
  1290. }
  1291.  
  1292. static    int    Receive_File (Name)
  1293. char    Name[];
  1294. {
  1295.     FILE    *Data_File;
  1296.     int        status;
  1297.     long    File_Length=0L;      /* For download resumption */
  1298.     char    Work_String[256];
  1299.     int        Packet_Len;
  1300.     int        i, n;
  1301.     char    yn;
  1302.     char    Dow_Type;
  1303.     buf_type *p;
  1304.     time_t  now;
  1305.  
  1306.     Dow_Type = 'D';         /* Assume normal downloading */
  1307.  
  1308.     Data_File = fopen( Name, UPDATE_OP );    /* open for r/w first */
  1309.  
  1310.     if ( Data_File != NULL ) {
  1311.     if ( (Our_DR > 1) && BP_Auto_Resume )
  1312.         Dow_Type = 'R';  /* Remote supports `Tf', let's try */
  1313.     else if ( Our_DR > 0 ) {
  1314.         ST_Display_String (STMsg, "File already exists.");
  1315.         ST_Yes_or_No ("Do you wish to resume downloading? ", &yn);
  1316.  
  1317.         if ( yn == 'Y' || yn == 'y' )
  1318.         Dow_Type = 'R';
  1319.         else
  1320.         ST_Display_String (STMsg, "File being overwritten.");
  1321.     }
  1322.     }
  1323.  
  1324.     switch( Dow_Type ) {
  1325.     case 'D':
  1326.     if( Data_File )
  1327.         fclose( Data_File );    /* close the read/write file */
  1328.     Data_File = fopen( Name, WRITE_OP );        /* open for write */
  1329.     if (Data_File == NULL) {
  1330.         Send_Failure ("CCannot create file");
  1331.         return(FALSE);
  1332.     }
  1333.     Send_ACK();
  1334.     break;
  1335.  
  1336.     case 'R' :                     /* Resume download */
  1337.     ST_Display_String (STMsg, "Calculating CRC");
  1338.     p = &SA_Buf [SA_Next_to_Fill];
  1339.     if ( Dow_Type == 'R' ) {
  1340.         checksum = Init_CRC (0xffff);
  1341.         do {
  1342.         n = fread (&p->buf [0], 1, Buffer_Size, Data_File);
  1343.         for ( i = 0 ; i < n ; i++ )
  1344.             checksum = Upd_CRC(p->buf[i]);
  1345.         } while( n > 0 );
  1346.     } else
  1347.         checksum = 0;
  1348.  
  1349.     p->buf [0] = 'T';
  1350.     p->buf [1] = 'r';
  1351.  
  1352.     Packet_Len = 2;
  1353.     File_Length = ftell(Data_File);
  1354.  
  1355.     ltoa (File_Length, Work_String);
  1356.     strcat( Work_String, " " );
  1357.  
  1358.     for ( i = 0 ; i < strlen(Work_String); i++ ) {
  1359.         p->buf [Packet_Len] = Work_String [i];
  1360.         Packet_Len++;
  1361.     }
  1362.  
  1363.     ltoa ((long)checksum, Work_String);
  1364.     strcat( Work_String, " " );
  1365.  
  1366.     for ( i = 0 ; i < strlen(Work_String) ; i++ ) {
  1367.         p->buf [Packet_Len] = Work_String [i];
  1368.         Packet_Len++;
  1369.     }
  1370.  
  1371.     if ( !send_Packet (Packet_Len - 1) ) {
  1372.         fclose (Data_File);
  1373.         return(FALSE);
  1374.     }
  1375.     if ( !SA_Flush() ) {
  1376.         fclose (Data_File);
  1377.         return(FALSE);
  1378.     }
  1379.  
  1380.     R_File_Size = File_Length;
  1381.     ST_Display_Value (STDowSize, R_File_Size);
  1382.     ST_Display_String (STMsg, "Host calculating CRC...");
  1383.     Resume_Flag = TRUE;
  1384.     break;
  1385.     }
  1386. /*
  1387.   Process each incoming Packet until 'TC' Packet received or failure
  1388. */
  1389.     R_Packet_Count = 0;
  1390.     S_Packet_Count = 0;
  1391.  
  1392.     if( BP_Use_File_Size )
  1393.     R_Remaining = BP_File_Size;
  1394.     else
  1395.     R_Remaining = 0;
  1396.  
  1397.     while ( TRUE ) {
  1398.     if ( Read_Packet (FALSE, FALSE) ) {
  1399.         switch (R_buffer[0]) {
  1400.             case 'N' :
  1401.         if ( Resume_Flag ) {
  1402.             ST_Display_String( STMsg, "Resuming Download" );
  1403.             Resume_Flag = FALSE;
  1404.         }
  1405.         status = fwrite( &R_buffer[1], 1, R_Size - 1, Data_File );
  1406.  
  1407.         if ( (status != (R_Size - 1)) ) {
  1408.             ST_Display_String (STMsg, "Write failure...aborting");
  1409.             Send_Failure ("EWrite failure");
  1410.             Check_Keep (Data_File, Name);
  1411.             return(FALSE);
  1412.                 }
  1413.                 R_File_Data = R_File_Data + (R_Size - 1);
  1414.         ST_Display_Value (STDataRead, R_File_Data);
  1415.                 R_File_Size = R_File_Size +  (status);
  1416.                 ST_Display_Value (STDowSize, R_File_Size);
  1417.                 time(&now);
  1418.         Time_Estimate = now - e_timer;
  1419.                 ST_Display_Value (STElapsed, Time_Estimate);
  1420.  
  1421.         if ( Time_Estimate != 0 ) {
  1422.             Com_Rate = R_Com_Data / Time_Estimate;
  1423.                     Data_Rate = R_File_Data / Time_Estimate;
  1424.                     ST_Display_Value (STComRate, Com_Rate);
  1425.                     ST_Display_Value (STDataRate, Data_Rate);
  1426.         } else
  1427.             Data_Rate = 0;
  1428.  
  1429.         if ( R_Remaining != 0 ) {
  1430.             R_Remaining = R_Remaining - (R_Size - 1);
  1431.                     ST_Display_Value (STDowRem, R_Remaining);
  1432.             if ( Data_Rate != 0 ) {
  1433.             Time_Estimate = R_Remaining / Data_Rate;
  1434.                         ST_Display_Value (STRemTime, Time_Estimate);
  1435.                     }
  1436.         }
  1437.                 Send_ACK();
  1438.                 break;
  1439.  
  1440.             case 'T' :
  1441.         if (R_buffer[1] == 'C') {
  1442.             ST_Display_String (STMsg, "*** Transfer Complete ***");
  1443.                     status = fclose (Data_File);
  1444.  
  1445.                     if ( status == EOF ) {
  1446.             ST_Display_String (STMsg, 
  1447.                 "Failure during close...aborting");
  1448.             Send_Failure ("EError during close");
  1449.                         Check_Keep (Data_File, Name);
  1450.                         return(FALSE);
  1451.             }
  1452.  
  1453.                     Send_ACK();
  1454.                     return(TRUE);
  1455.                 } else if ( R_buffer [1] == 'I' ) {
  1456.             Send_ACK();
  1457.             Process_File_Information();
  1458.         } else if ( (R_buffer [1] == 'f') && BP_Auto_Resume ) {
  1459.             fclose (Data_File);       /* So...replace the file */
  1460.             Data_File = fopen(Name, WRITE_OP);
  1461.             if ( Data_File == NULL ) {
  1462.             Send_Failure ("CCannot create file");
  1463.             ST_Display_String (STMsg,
  1464.                 "CRC check failed; cannot create file");
  1465.             return(FALSE);
  1466.             }
  1467.             if (Our_FI != 0 || BP_Use_File_Size)
  1468.                         R_Remaining = R_Remaining + R_File_Size;
  1469.  
  1470.                     R_File_Size = 0;
  1471.                     ST_Display_String (STMsg,
  1472.                 "CRC check failed; overwriting file");
  1473.             Resume_Flag = FALSE;
  1474.             time(&e_timer);
  1475.             S_Com_Data = 0;
  1476.             R_Com_Data = 0;
  1477.                     Send_ACK();
  1478.         } else {
  1479.                     ST_Display_String (STMsg,
  1480.                 "Invalid termination Packet...aborting");
  1481.                     Send_Failure ("NInvalid T Packet");
  1482.                     Check_Keep (Data_File, Name);
  1483.                     return(FALSE);
  1484.         }
  1485.         break;
  1486.  
  1487.         case 'F' :
  1488.         Send_ACK();
  1489.                 ST_Display_String (STMsg,
  1490.                 "Failure Packet received...aborting");
  1491.                 Check_Keep (Data_File, Name);
  1492.                 return(FALSE);
  1493.                 break;
  1494.  
  1495.         }
  1496.     } else {
  1497.         if (!Aborting)
  1498.         ST_Display_String (STMsg, "Download failure");
  1499.             Check_Keep (Data_File, Name);
  1500.             return(FALSE);
  1501.     }
  1502.     }
  1503. } /* Receive_File */
  1504.  
  1505. /* =================================================================== */
  1506.  
  1507. int    BP_DLE_Seen()
  1508. {
  1509.     int     i;
  1510.  
  1511.     Port_Update_Rate = 256;
  1512.     ST_Initialize(0);
  1513.     if ( !read_byte() )
  1514.     return 0;
  1515.     if (ch != 'B')
  1516.     return 0;
  1517.  
  1518.     SA_Next_to_ACK  = 0;    /* Initialize Send-ahead variables */
  1519.     SA_Next_to_Fill = 0;
  1520.     SA_Waiting      = 0;
  1521.     Aborting        = FALSE;
  1522.     Packet_Received = FALSE;
  1523.  
  1524.     switch (PortBps) {
  1525.     case bps110:
  1526.     case bps150:
  1527.     case bps300:
  1528.         Port_Update_Rate = 32;
  1529.     break;
  1530.     case bps600:
  1531.     case bps1200:
  1532.         Port_Update_Rate = 64;
  1533.     break;
  1534.     case bps1800 :
  1535.     case bps2400:
  1536.         Port_Update_Rate = 128;
  1537.     break;
  1538.     case bps4800:
  1539.     case bps9600:
  1540.         Port_Update_Rate = 256;
  1541.     break;
  1542.     }
  1543.  
  1544.     R_Counter   = 0;
  1545.     S_Counter   = 0;
  1546.     R_File_Data = 0;
  1547.     S_File_Data = 0;
  1548.     R_Com_Data  = 0;
  1549.     S_Com_Data  = 0;
  1550.     S_Packet_Count = 0;
  1551.     R_Packet_Count = 0;
  1552.     S_File_Size = 0;
  1553.     R_File_Size = 0;
  1554.     S_Error_Count = 0;
  1555.     R_Error_Count = 0;
  1556.     Resume_Flag = FALSE;
  1557.  
  1558.     if (Read_Packet (TRUE, FALSE)) {
  1559.     switch (R_buffer[0]) {
  1560.     case 'T':                      /* File Transfer Application */
  1561.         ST_Initialize(0);
  1562.         ST_Display_Value (STComRead, R_Com_Data);
  1563.         S_Com_Data = 0;
  1564.         R_Com_Data = 0;
  1565.         time(&e_timer);
  1566.  
  1567.         switch (R_buffer[1]) {
  1568.         case 'D' :
  1569.         ST_Display_String (STUpDow, "Downloading ");
  1570.         break;
  1571.         case 'U' :
  1572.              ST_Display_String (STUpDow, "Uploading ");
  1573.         break;
  1574.         default:
  1575.         ST_Display_String (STMsg, "Unimplemented Transfer Function");
  1576.         Send_Failure ("NUnimplemented Transfer function");
  1577.         ST_Terminate();
  1578.         return 0;
  1579.         }
  1580.  
  1581.         switch (R_buffer[2]) {
  1582.         case 'A':
  1583.         ST_Display_String (STType, "ASCII");
  1584.         break;
  1585.         case 'B':
  1586.         ST_Display_String (STType, "Binary");
  1587.         break;
  1588.         default:
  1589.         ST_Display_String (STMsg, "Unimplemented File Type");
  1590.         Send_Failure ("NUnimplemented file type");
  1591.         ST_Terminate();
  1592.         return 0;
  1593.         }
  1594.  
  1595.         i = 2;
  1596.         memset(filename,0,sizeof(filename));
  1597.  
  1598.         while ((R_buffer[i] != 0) && (i < R_Size - 1)) {
  1599.         i = i + 1;
  1600.         filename[i-3] = R_buffer[i];
  1601.         }
  1602.  
  1603.         ST_Display_String (STFile, filename);
  1604.         S_Packet_Count =  (0);
  1605.         R_Packet_Count =  (0);
  1606.  
  1607.         if (R_buffer[1] == 'U')
  1608.         Send_File (filename);
  1609.         else
  1610.         Receive_File (filename);
  1611.  
  1612.         ST_Terminate();
  1613.         return 1;
  1614.         break;
  1615.  
  1616.     case '+':          /* Received Transport Parameters Packet */
  1617.         Do_Transport_Parameters();
  1618.         break;
  1619.  
  1620.     default:    /* Unknown Packet; tell the host we don't know */
  1621.         Send_Failure ("NUnknown Packet Type");
  1622.             break;
  1623.  
  1624.     }  /* of case */
  1625.     }    /* of if Read_Packet then*/
  1626.  
  1627.     return 0;
  1628. } /* DLE_Seen */
  1629.